package com.liuya.shiro;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.annotation.Resource;

import com.liuya.common.PropertiesUtil;
import com.liuya.common.SecurityUtil;
import com.liuya.safe.model.SafeUser;
import com.liuya.safe.user.service.UserManagerService;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.time.DateUtils;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.DisabledAccountException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.pam.UnsupportedTokenException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

/**
 * @Author 刘亚
 * @Date 2016/12/15
 */
public class AuthenticationRealm extends AuthorizingRealm {

    @Resource(name = "userManagerService")
    private UserManagerService userManager;
    /**
     * 获取用户身份验证，返回验证后的用户身份信息。注意：只是验证用户身份，并未验证权限。
     */
    protected AuthenticationInfo doGetAuthenticationInfo(org.apache.shiro.authc.AuthenticationToken token) {
        AuthenticationToken authTok = (AuthenticationToken) token;
        String uname = authTok.getUsername();
        String upwd = new String(authTok.getPassword());
        String host = authTok.getHost();

        if (uname != null && upwd != null) {
            SafeUser user = this.userManager.selectByName(uname);
            if (user == null)
                throw new UnknownAccountException();
            if (!user.getEnable())
                throw new DisabledAccountException();
            user.setLoginIp(host);
            user.setLoginTime(new Date());
            user.setLoginFailureCount(0);
            if (user.getLocked() == 1) {
                Date lockedDate = user.getLoginTime();
                Date currDate = DateUtils.addMinutes(lockedDate, PropertiesUtil.getInt("locked.amount"));
                //判断用户锁定是否已到期，到期即可启用
                if (new Date().after(currDate)) {
                    user.setLoginFailureCount(0);
                    user.setLocked(0);
                    user.setLoginTime(null);
                    this.userManager.update(user);
                } else {
                    throw new LockedAccountException();
                }
            }
            int locked = 0;
            //登录失败，密码错误，抛出异常
            if (!SecurityUtil.encryptMD5Hex(upwd).equals(user.getPassword())) {
                locked = user.getLoginFailureCount() + 1;
                if (locked >= PropertiesUtil.getInt("locked.count")) {
                    user.setLocked(1);
                }
                user.setLoginTime(new Date());
                user.setLoginFailureCount(locked);
                this.userManager.update(user);
                throw new IncorrectCredentialsException();
            } else {
                user.setLoginFailureCount(0);
                user.setLocked(0);
                user.setLoginTime(null);
            }

            this.userManager.update(user);
            return new SimpleAuthenticationInfo(new Principal(user.getId(), uname), upwd, getName());
        }
        throw new UnknownAccountException();
    }

    /**
     * 验证用户权限，注意只是验证权限，也就是用户必须先通过上面的用户身份验证才可。
     */
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        Principal principal = (Principal) principals.fromRealm(getName()).iterator().next();
        if (principal != null) {
            List<String> list = null;
//            list = this.userManager.selectAuthorities(principal.getId());
            if (list != null) {
                SimpleAuthorizationInfo sain = new SimpleAuthorizationInfo();
                sain.addStringPermissions(list);
                return sain;
            }
        }
        return null;
    }

    private List test(){
        List list = new ArrayList();
        list.add("admin:product");
        list.add("admin:productCategory");
        list.add("admin:parameterGroup");
        list.add("admin:attribute");
        list.add("admin:specification");
        list.add("admin:brand");
        list.add("admin:productNotify");
        list.add("admin:order");
        list.add("admin:print");
        list.add("admin:payment");
        list.add("admin:refunds");
        list.add("admin:shipping");
        list.add("admin:returns");
        list.add("admin:deliveryCenter");
        list.add("admin:deliveryTemplate");
        list.add("admin:member");
        list.add("admin:memberRank");
        list.add("admin:memberAttribute");
        list.add("admin:review");
        list.add("admin:consultation");
        list.add("admin:navigation");
        list.add("admin:article");
        list.add("admin:articleCategory");
        list.add("admin:tag");
        list.add("admin:friendLink");
        list.add("admin:adPosition");
        list.add("admin:ad");
        list.add("admin:template");
        list.add("admin:cache");
        list.add("admin:static");
        list.add("admin:index");
        list.add("admin:promotion");
        list.add("admin:coupon");
        list.add("admin:seo");
        list.add("admin:sitemap");
        list.add("admin:statistics");
        list.add("admin:sales");
        list.add("admin:salesRanking");
        list.add("admin:purchaseRanking");
        list.add("admin:deposit");
        list.add("admin:setting");
        list.add("admin:area");
        list.add("admin:paymentMethod");
        list.add("admin:shippingMethod");
        list.add("admin:deliveryCorp");
        list.add("admin:paymentPlugin");
        list.add("admin:storagePlugin");
        list.add("admin:admin");
        list.add("admin:role");
        list.add("admin:message");
        list.add("admin:log");
        return list;
    }
}
